package controller

import (
	"fmt"
	"github.com/gookit/validate"
	"kong-social-api/commons/base/controller"
	"kong-social-api/modules/common/code/constants"
	code "kong-social-api/modules/common/code/controller"
	"kong-social-api/modules/login/model/context"
	"kong-social-api/modules/login/service"
	"kong-social-api/utils/rdb"
	"strconv"
)

// 登录控制器
type LoginController struct {
	controller.BaseController
}

// 登录的方法
func (web *LoginController) Login() {
	// 获取登录请求的的上下文参数
	loginContext := context.LoginContext{}
	// 绑定参数到结构体中
	web.BindJSON(&loginContext)
	// 对登录用户信息进行校验
	validation := validate.Struct(loginContext)
	if !validation.Validate() {
		web.FailWithValidatorData(validation)
		return
	}

	// 获取用户IP
	userIp := web.GetIpAddr()
	// 缓存的key
	countKey := fmt.Sprintf("LOGIN:CODE:ERRCOUNT:" + userIp)
	get, _ := rdb.RdbGet(countKey)
	errorCount, _ := strconv.ParseInt(get, 10, 64)
	// 如果错误次数超过三次，才显示验证码
	if errorCount >= 3 || loginContext.ErrorCount >= 3 {
		// 判断是否输入验证码
		if len(loginContext.CaptchaId) == 0 || len(loginContext.VerifyCode) == 0 {
			web.FailCodeMsg(constants.VAL_CODE_INPUT, constants.VAL_CODE_INPUT_MSG)
			return
		}

		//  验证码校验
		codeController := code.CodeController{}
		verifyCode := codeController.VerifyCode(loginContext.CaptchaId, loginContext.VerifyCode)
		if !verifyCode {
			web.FailCodeMsg(constants.VAL_CODE_FAIL, constants.VAL_CODE_FAIL_MSG)
			return
		}
	}

	// 开始执行登录逻辑
	loginService := service.LoginService{}
	vo, validErr := loginService.LoginByPhoneAndPassword(&loginContext)
	if validErr != nil {
		// 记录错误次数
		rdb.RdbIncr(countKey)
		// 把key设置一个过期时间，防止用户恶意输入请求，写入到缓存中，可以使用过期时间自动取清理那些错误的缓存的账号和信息
		if errorCount == 0 {
			rdb.RdbExKey(countKey, 120)
		}
		// 如果捕捉到错误次数，就加一次
		web.FailCodeMsgData(constants.USER_ERROR_CODE, validErr.Error(), errorCount+1)
		return
	}
	// 如果登录成功，就直接把缓存中的计数器给删除掉。
	rdb.RdbDel(countKey)
	web.Ok(vo)
}

// 退出登录
func (web *LoginController) ToLoginOut() {
	// 获取用户的id
	uuid := web.GetUuid()
	// 获取缓存中的key
	loginCacheKey := fmt.Sprintf("LOGIN:USER:%s", uuid)
	// 直接删除
	rdb.RdbDel(loginCacheKey)
	// 4：退出成功
	web.Ok("success")
}
